package com.nenude.corejava.jdbc.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.nenude.corejava.jdbc.bean.Users;
import com.nenude.corejava.jdbc.dao.IUsersDao;
import com.nenude.corejava.jdbc2.DBHelper;

/**
 * 实现类
 * @author admin
 */

public class UserDaoImpl implements IUsersDao {

	@Override
	public boolean add(Users param) {
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;

		try {
			String sql = "insert into users(id,name,age,birthdate) values(SEQ_USERS.NEXTVAL,?,?,?)";
			stmt = conn.prepareStatement(sql);
			stmt.setString(1, param.getName());
			stmt.setInt(2, param.getAge());

			// 参数值是java.sql.Date,只能保存年月日;这里一般需要把until.Date转换为sql.Date
			// stmt.setDate(3, new
			// java.sql.Date(param.getBirthDate().getTime()));

			// 参数值是java.sql.Time,只能保存年月日;这里一般需要把until.Date转换为sql.Time
			// stmt.setTime(3, new
			// java.sql.Time(param.getBirthDate().getTime()));

			// 参数值是java.sql.Timestamp,只能保存年月日时分秒;这里一般需要把until.Date转换为sql.Timestamp
			stmt.setTimestamp(3, new java.sql.Timestamp(param.getBirthDate()
					.getTime()));
			int count = stmt.executeUpdate();// executeUpdate()会返回sql更新数据时更新了多少行，更新行数；

			if (count == 1) {
				// 新增成功，返回return---在项目注释不能写语法，要写业务说明
				return true;// 一个方法内部可以有多个return
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public boolean edit(Users param) {
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;

		try {
			String sql = "update users set name=?,age=?,birthdate=? where id=?";

			stmt = conn.prepareStatement(sql);
			
			stmt.setInt(4, param.getId());
			stmt.setString(1, param.getName());
			stmt.setInt(2, param.getAge());
			stmt.setTimestamp(3, new java.sql.Timestamp(param.getBirthDate()
					.getTime()));
			int count = stmt.executeUpdate();// executeUpdate()会返回sql更新数据时更新了多少行，更新行数；

			if (count == 1) {
				// 新增成功，返回return---在项目注释不能写语法，要写业务说明
				return true;// 一个方法内部可以有多个return
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public boolean deleteById(int id) {
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;
		try {
			String sql = "delete from  users  where id=?";

			stmt = conn.prepareStatement(sql);
			stmt.setInt(1, id);

			int count = stmt.executeUpdate();// executeUpdate()会返回sql更新数据时更新了多少行，更新行数；

			if (count == 1) {
				// 新增成功，返回return---在项目注释不能写语法，要写业务说明
				return true;// 一个方法内部可以有多个return
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public Users findById(int id) {
		Users users = null;
		// 1·注册驱动 2·建立connection连接
		Connection conn = DBHelper.openConnection();
		// Statement statement; //可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击，在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement=conn.createStatement();

		try {
			// 3·打开里连接状态
			String sql = "select id,name,age,birthdate from users where  id=?";// 注意不要拼接sql//
																						// 占位符?
			stmt = conn.prepareStatement(sql);
			// 4·执行sql
			// 如果sql有参数，即有问号就要进行参数填充
			stmt.setInt(1, id);// 在执行之前传参
			rs = stmt.executeQuery();// 查询语句执行查询，更新语句执行更新

			// 5·对sql执行结果进行处理
			if (rs.next()) { // 根据主键或唯一键查询数据，要么有一条数据，要么没有数据，可以使用if进行判断
				int id0 = rs.getInt(1);// 可以根据序列号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据（没有别名就用列名）
				int age = rs.getInt("age");

				// 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");

				users = new Users(id0, name, age, birthDate);

			}

		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			// 6·关闭连接(从小-->大)
			DBHelper.closeAll(rs, stmt, conn);
		}
		return users;

	}

	@Override
	public List<Users> findAll() {
		// 定义一个集合
		List<Users> list = new ArrayList<Users>();

		// 1·注册驱动 2·建立connection连接
		Connection conn = DBHelper.openConnection();
		// Statement statement; //可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击，在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement=conn.createStatement();

		try {
			// 3·打开里连接状态
			String sql = "select id,name,age,birthdate from users";
			stmt = conn.prepareStatement(sql);
			// 4·执行sql
			rs = stmt.executeQuery();// 查询语句执行查询，更新语句执行更新

			// 5·对sql执行结果进行处理
			while (rs.next()) { // next()方法从结果集中取出一行数据，如果有数据返回true,没有返回false

				int id = rs.getInt(1);// 可以根据序列号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据（没有别名就用列名）
				int age = rs.getInt("age");

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回年月日
				// 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回年月日
				// birthDate=rs.getDate("birthDate"); //场景：在入学日期、入职日期

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回时分秒
				// birthDate=rs.getTime("birthDate"); //场景：火车、班车的发车时间、飞机的起飞时刻表

				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}

		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			// 6·关闭连接(从小-->大)
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;
	}

	@Override
	public List<Users> findByExample(Users param) {

		// 定义一个集合
		List<Users> list = new ArrayList<Users>();

		// 1·注册驱动 2·建立connection连接
		Connection conn = DBHelper.openConnection();
		// Statement statement; //可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击，在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement=conn.createStatement();

		try {
			// 3·打开里连接状态
			String sql = "select id,name,age,birthdate from users where name like ?";// 注意不要拼接sql//
																						// 占位符?
			stmt = conn.prepareStatement(sql);
			// 4·执行sql
			// 如果sql有参数，即有问号就要进行参数填充
			stmt.setString(1, "%" + param.getName() + "%");// 在执行之前传参

			rs = stmt.executeQuery();// 查询语句执行查询，更新语句执行更新

			// 5·对sql执行结果进行处理
			while (rs.next()) { // next()方法从结果集中取出一行数据，如果有数据返回true,没有返回false

				int id = rs.getInt(1);// 可以根据序列号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据（没有别名就用列名）
				int age = rs.getInt("age");

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回年月日
				// 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回年月日
				// birthDate=rs.getDate("birthDate"); //场景：在入学日期、入职日期

				// java.sql.getTimestamp,getTimestamp是java.sql.Date 的子类，可以返回时分秒
				// birthDate=rs.getTime("birthDate"); //场景：火车、班车的发车时间、飞机的起飞时刻表

				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}

		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			// 6·关闭连接(从小-->大)
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;

	}

	@Override
	public List<Users> findByPager(int page, int size) {

		// 定义一个集合
		List<Users> list = new ArrayList<Users>();

		// 1·注册驱动 2·建立connection连接
		Connection conn = DBHelper.openConnection();
		// Statement statement; //可能造成sql注入攻击
		PreparedStatement stmt = null;// 可以防止sql注入攻击，在批量更新时具有更好的性能
		ResultSet rs = null;
		// statement=conn.createStatement();

		try {
			// 3·打开里连接状态
			String sql = "select * from "
					+ "(select rownum rn ,id,name,age,birthdate from users where rownum<=?) where rn>?";
			stmt = conn.prepareStatement(sql);
			// 4·执行sql
			// 如果sql有参数，即有问号就要进行参数填充
			stmt.setInt(1, page * size);// 参数的序号是从1开始的，1表示第一个参数
			stmt.setInt(2, (page - 1) * size);

			rs = stmt.executeQuery();// 查询语句执行查询，更新语句执行更新

			// 5·对sql执行结果进行处理
			while (rs.next()) { // next()方法从结果集中取出一行数据，如果有数据返回true,没有返回false

				int id = rs.getInt("id");// 可以根据序列号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据（没有别名就用列名）
				int age = rs.getInt("age");

				// 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthdate");
				Users users = new Users(id, name, age, birthDate);
				list.add(users);
			}

		} catch (SQLException e) {

			e.printStackTrace();
		} finally {
			// 6·关闭连接(从小-->大)
			DBHelper.closeAll(rs, stmt, conn);
		}
		return list;

	}

	//批量更新
	@Override
	public int deleteByIds(int[] ids) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;
	
		// 业务说明：批量删除数据，只要有一条删除失败，则所有的都不删除

		try {
			connection.setAutoCommit(false);//关闭自动提交功能，开启数据库事务
			String sql = "delete from users where id=?";
			stmt = connection.prepareStatement(sql);
			for (int id : ids) {
				stmt.setInt(1, id);
				stmt.addBatch();// 批量发送，每循环一次就是一批数据
			}
			int[] counts = stmt.executeBatch();// 执行一个批量更新,会返回一个数组，保存每批数据更新的情况，每批数据更新的数量（要么是0，要么是1）
			for (int i : counts) {
				if (i == 1) {// 统计有多少批数据删除成功
					result++;
				}
			}
			if (result==ids.length) {
				connection.commit();//提交事务
				connection.setAutoCommit(true);//开启（还原）数据库事务
			}else {
				connection.rollback();//回滚事务
			}

		} catch (SQLException e) {
			e.printStackTrace();
           if (connection!=null) {//删除数据，如有部分删除异常则需要全部回滚
        	   try {
				connection.rollback();
				connection.setAutoCommit(true);
				
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
			
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;
	}
	
	

	@Override
	public int addAll(List<Users> users) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;
		// 业务说明：批量新增数据，只要有一条新增失败，则所有的都不新增
		try {
			connection.setAutoCommit(false);//关闭自动提交功能，开启数据库事务
			String sql = "insert into users(id,name,age,birthdate) values(SEQ_USERS.NEXTVAL,?,?,?)";
			stmt = connection.prepareStatement(sql);
			for (Users user : users) {
				
				stmt =connection.prepareStatement(sql);
				stmt.setString(1, user.getName());
				stmt.setInt(2, user.getAge());
				// 参数值是java.sql.Timestamp,只能保存年月日时分秒;这里一般需要把until.Date转换为sql.Timestamp
				stmt.setTimestamp(3, new java.sql.Timestamp(user.getBirthDate()
						.getTime()));
				stmt.addBatch();// 批量发送，每循环一次就是一批数据
			}
			int[] counts = stmt.executeBatch();// 执行一个批量更新,会返回一个数组，保存每批数据更新的情况，每批数据更新的数量（要么是0，要么是1）
			for (int i : counts) {
				if (i == 1) {// 统计有多少批数据新增成功
					result++;
				}
			}
			if (result==users.size()) {
				connection.commit();//提交事务
				connection.setAutoCommit(true);//开启（还原）数据库事务
			}else {
				connection.rollback();//回滚事务
			}

		} catch (SQLException e) {
			e.printStackTrace();
           if (connection!=null) {//新增数据，如有部分删除异常则需要全部回滚
        	   try {
				connection.rollback();
				connection.setAutoCommit(true);
				
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
			
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;
	}

	@Override
	public int editAll(List<Users> users) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;
		// 业务说明：批量新增数据，只要有一条新增失败，则所有的都不新增
		try {
			connection.setAutoCommit(false);//关闭自动提交功能，开启数据库事务
			String sql = " update users set age=?,birthdate=? where id=?";
			stmt = connection.prepareStatement(sql);
			for (Users user : users) {
				
				stmt.setInt(3, user.getId());
				stmt.setInt(1, user.getAge());
				stmt.setTimestamp(2, new java.sql.Timestamp(user.getBirthDate().getTime()));
				stmt.addBatch();// 批量发送 ,每循环一次就是一批数据
				
			}
			int[] counts = stmt.executeBatch();// 执行一个批量更新,会返回一个数组，保存每批数据更新的情况，每批数据更新的数量（要么是0，要么是1）
			for (int i : counts) {
				if (i == 1) {// 统计有多少批数据新增成功
					result++;
				}
			}
			if (result==users.size()) {
				connection.commit();//提交事务
				connection.setAutoCommit(true);//开启（还原）数据库事务
			}else {
				connection.rollback();//回滚事务
			}

		} catch (SQLException e) {
			e.printStackTrace();
           if (connection!=null) {//新增数据，如有部分删除异常则需要全部回滚
        	   try {
				connection.rollback();
				connection.setAutoCommit(true);
				
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
			
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;
	}

}
